www.gusucode.com > C++ Primer 书籍源代码源码程序 > C++ Primer 书籍源代码源码程序/code/13/old/smart-ptr.cpp

    //Download by http://www.NewXing.com
#include <iostream>
using std::ostream; using std::cout; using std::endl;
#include <string>
#include <cstddef>
using std::size_t;

//private class for use by HasPtr only
class U_Ptr {
	friend class HasPtr;
	int *ip;
	size_t use;
	U_Ptr(int *p): ip(p), use(1) { }
	~U_Ptr() { delete ip; }
};

class HasPtr {
public:
    // HasPtr owns the pointer; p must have been dynamically allocated
    HasPtr(int *p, int i): ptr(new U_Ptr(p)), val(i) { }

    // copy members and increment the use count
    HasPtr(const HasPtr &orig):
       ptr(orig.ptr), val(orig.val) { ++ptr->use; }
    HasPtr& operator=(const HasPtr&);

    // if use count goes to zero, delete the U_Ptr object
    ~HasPtr() { if (--ptr->use == 0) delete ptr; } 

    friend ostream& operator<<(ostream&, const HasPtr&);
    // copy control and constructors as before

    // accessors must change to fetch value from U_Ptr object
    int *get_ptr() const { return ptr->ip; } 
    int get_int() const { return val; }

    // change the appropriate data member
    void set_ptr(int *p) { ptr->ip = p; }
    void set_int(int i) { val = i; }

    // return or change the value pointed to, so ok for const objects
    // Note: *ptr->ip is equivalent to *(ptr->ip)
    int get_ptr_val() const { return *ptr->ip; } 
    void set_ptr_val(int i) { *ptr->ip = i; }
private:
    U_Ptr *ptr;        // points to use-counted U_Ptr class
    int val;
};

HasPtr& HasPtr::operator=(const HasPtr &rhs)
{
    ++rhs.ptr->use;     // increment use count on rhs first
    if (--ptr->use == 0)
         delete ptr;    // if use count goes to 0 on this object, delete it
    ptr = rhs.ptr;      // copy the U_Ptr object
    val = rhs.val;      // copy the int member
    return *this;
}

ostream& operator<<(ostream &os, const HasPtr &hp)
{
    os << "*ptr: " << hp.get_ptr_val() << "\tval: " << hp.get_int() << endl;
    return os;
}

int main()
{
int obj = 0;

HasPtr ptr1(&obj, 42);
HasPtr ptr2(ptr1);
cout << "(1) ptr1: " << ptr1 << endl << "ptr2: " << ptr2 << endl;

ptr1.set_ptr_val(42); // sets object to which both ptr1 and ptr2 point
ptr2.get_ptr_val();   // returns 42

cout << "(2) ptr1: " << ptr1 << endl << "ptr2: " << ptr2 << endl;

ptr1.set_int(0);   // changes s member only in ptr1
ptr2.get_int();    // returns 42
ptr1.get_int();    // returns 0

cout << "(3) ptr1: " << ptr1 << endl << "ptr2: " << ptr2 << endl;
}

void f3()
{
int obj;
HasPtr p1(&obj, 42);
HasPtr p2(p1);  // p1 and p2 both point to same int object
HasPtr p3(p1);  // p1, p2, and p3 all point to same int object
}